package org.dromara.pay.adapter.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.pay.adapter.PayAdapter;
import org.dromara.pay.config.WxPayConfig;
import org.dromara.pay.config.WxPayProperties;
import org.dromara.pay.constant.PayType;
import org.dromara.pay.constant.PayWaysConstant;
import org.dromara.pay.constant.TopUpConstant;
import org.dromara.pay.domain.request.PayParam;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;


/**
 * 微信小程序支付
 *
 * @author zlj
 * @since 2023/7/28
 */
@Slf4j
@Component(PayWaysConstant.WX_XCX_PAY)
public class WxXcxPayAdapter implements PayAdapter {

    @Resource
    private WxPayProperties wxPayProperties;
    @Resource
    private WxPayConfig wxPayConfig;

    /**
     * 是否支持
     *
     * @param adapter 具体目标接口
     */
    @Override
    public boolean support(String adapter) {
        Object bean = null;
        try {
            bean = SpringUtil.getBean(adapter);
        } catch (Exception ignored) {
        }
        return bean instanceof WxXcxPayAdapter;
    }

    /**
     * 支付
     *
     * @param payParam 支付参数
     * @return 唤起支付参数
     */
    @Override
    public JSONObject pay(PayParam payParam) {
        String timeExpire = DateUtil.format(DateUtil.offsetMinute(DateUtils.getNowDate(), TopUpConstant.OUT_TIME), "yyyyMMddHHmmss");
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        wxPayUnifiedOrderRequest.setBody(payParam.getDesc());//自定
        wxPayUnifiedOrderRequest.setOutTradeNo(payParam.getOutTradeNo());
        wxPayUnifiedOrderRequest.setTotalFee(payParam.getAmount().multiply(new BigDecimal(100)).intValue());
        wxPayUnifiedOrderRequest.setTradeType(PayType.WECHATMINI.getType());
        wxPayUnifiedOrderRequest.setSpbillCreateIp(wxPayProperties.getSpbillCreateIp());
        wxPayUnifiedOrderRequest.setAttach(payParam.getAttach());
        wxPayUnifiedOrderRequest.setTimeExpire(timeExpire);
        wxPayUnifiedOrderRequest.setOpenid(LoginHelper.getOpenId());
//        wxPayUnifiedOrderRequest.setOpenid("oKKED7cHTAJTH8PmnWv8x9ym79b0");
        try {
            WxPayMpOrderResult orderResult = wxPayConfig.wxMiniService().createOrder(wxPayUnifiedOrderRequest);
            return JSONUtil.parseObj(JSONUtil.toJsonStr(orderResult));
        } catch (Exception e) {
            log.error("发起订单错误:", e);
            throw new ServiceException("发起订单错误，请重新下单");
        }
    }

    /**
     * 发起退款
     *
     * @param topUpId  订单编号
     * @param totalFee 支付总金额
     * @return true:成功 false:失败
     */
    @Override
    public boolean refund(Long topUpId, BigDecimal totalFee) {
        String outTradeNo = String.valueOf(topUpId);
        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
        refundRequest.setOutTradeNo(outTradeNo);
        refundRequest.setOutRefundNo(outTradeNo);
        refundRequest.setTotalFee(totalFee.multiply(new BigDecimal(100)).intValue());
        refundRequest.setRefundFee(totalFee.multiply(new BigDecimal(100)).intValue());
        refundRequest.setRefundDesc("订单退款");
        refundRequest.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());
        try {
            WxPayRefundResult result = wxPayConfig.wxMiniService().refund(refundRequest);
            //REFUND_SUCCESS
            if ("SUCCESS".equals(result.getReturnCode()) && "SUCCESS".equals(result.getResultCode())) {
                // 退款发起成功
                return true;
            } else {
                // 退款发起失败
                return false;
            }
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return false;
    }
}

